/*
 * @Author      : ZhouQiJun
 * @Date        : 2025-08-07 02:20:10
 * @LastEditors : ZhouQiJun
 * @LastEditTime: 2025-08-07 03:01:51
 * @Description : 类型安全的属性访问工具函数
 */
import type { PlainObj } from '@ol/types'
import { isFunction, isNil } from 'es-toolkit'

/**
 * 属性获取器函数类型
 * @template T - 目标对象类型
 * @template R - 返回值类型
 */
type PropertyGetter<T = unknown, R = unknown> = (target: T, ...args: unknown[]) => R

/**
 * 通用属性获取函数
 *
 * 当属性可能是一个值或一个获取值的函数时，此函数提供统一访问方式。
 * - 如果 property 是函数，则调用它并传入 target 和 args
 * - 如果 property 不是函数，则直接返回它
 *
 * @template T - 期望返回值的类型
 * @template U - 目标对象类型（可选）
 *
 * @param {T | PropertyGetter<U, T>} property - 属性值或属性获取函数
 * @param {U} [target] - 当 property 为函数时传入的目标对象
 * @param {...unknown[]} args - 当 property 为函数时传入的额外参数
 *
 * @returns {T} - 获取到的属性值
 *
 * @example
 * // 直接返回值
 * getter(42); // => 42
 *
 * @example
 * // 调用函数获取值
 * getter((obj) => obj.name, { name: 'John' }); // => 'John'
 */
export function getter<T, U = unknown>(
  property: T | PropertyGetter<U, T>,
  target?: U,
  ...args: unknown[]
): T {
  return isFunction(property) ? (property as PropertyGetter<U, T>)(target as U, ...args) : property
}

/**
 * 从目标对象中获取属性值
 *
 * 与 getter 的区别：
 * - 当 property 不是函数时，getter 直接返回 property
 * - 而 valueOf 会返回 target[property]
 *
 * @template T - 期望返回值的类型
 * @template U - 目标对象类型（必须为对象类型）
 *
 * @param {keyof U | PropertyGetter<U, T>} property - 属性名或属性获取函数
 * @param {U} target - 目标对象
 * @param {...unknown[]} args - 当 property 为函数时传入的额外参数
 *
 * @returns {T} - 获取到的属性值
 *
 * @example
 * // 通过属性名获取值
 * valueOf('name', { name: 'John' }); // => 'John'
 *
 * @example
 * // 通过函数获取值
 * valueOf((obj) => obj.age, { age: 30 }); // => 30
 */
export function valueOf<K extends PropertyKey, U = PlainObj>(
  property: keyof U | PropertyGetter<U, K>,
  target: U,
  ...args: unknown[]
): K | undefined {
  if (isFunction(property)) {
    return property(target, ...args)
  }
  if (isNil(target)) return undefined
  return target[property] as K
}
